#ifndef __KEW_STDLIB_H__
#define __KEW_STDLIB_H__

#include <kew/c-vm.h>
#include <glib.h>
#include <kew/glibext.h>

G_BEGIN_DECLS

typedef struct _KewActionObject KewActionObject;
typedef struct _KewDynamicVariableObject KewDynamicVariableObject;
typedef struct _KewRelationObject KewRelationObject;
typedef struct _KewErrorObject KewErrorObject;
typedef struct _KewListObject KewListObject;
typedef struct _KewStringObject KewStringObject;
    
    


/* INITIALIZATION
 * This registers all the selectors and other resources and returns the well-known
 * objects for the base library.
 * 
 * Regarding security contexts - the standard library considers itself to be in a NULL
 * security context.  Is this correct, I wonder?
 * The problem with it is that it may inhibit you from doing introspection.  But there are
 * 2 interesting cases: where you want to introspect on methods, it is ok, provided you
 * cannot break their encapsulation (this should always be allowed), and 2 is where you
 * want to break encapsulation of the object and access its capture slots, which is not
 * really a good idea, since all stdlib objects do not have true capture slots.
 */

GHashTable *kew_boot_standard_library(KewVM *vm);




/* TYPES
 */
 
KewObject *kew_check_type(KewDynamicEnvironment *env, KewStaticEnvironment *security_context, KewObject *object, char *informal_name, KewSelector conversion_selector);
gboolean kew_is_type(KewObjectType *type, KewObject *object);

KewDynamicVariableObject *kew_check_dynamic_variable(KewDynamicEnvironment *env, KewStaticEnvironment *security_context, KewObject *object);






/* ACTIONS (aka. blocks)
 */

struct _KewActionObject {
    KewObject super;
};

KEW_DECLARE_METHOD(kew_action_call_ensuring);





/* DYNAMIC VARIABLES
 */

struct _KewDynamicVariableObject {
    KewObject super;
    GSList *value_stack;
};

void kew_dynamic_variable_push(KewDynamicEnvironment *env, KewDynamicVariableObject *dynvar, KewObject *value);

void kew_dynamic_variable_pop(KewDynamicEnvironment *env, KewDynamicVariableObject *dynvar);

KEW_DECLARE_METHOD(kew_action_set_dynamic_variable);
KEW_DECLARE_METHOD(kew_dynamic_variable_read);




/* RELATIONS
/* Bidirectional n-way relationships between objects.
 * An alternative form of state to variables, relations are more
 * complicated and more powerful.
 */

struct _KewRelationFactory {
    KewObject super;
};

struct _KewRelationObject {
    KewObject super;
    KewRelationObject *inverse;
};




/* ERROR OBJECTS
 * Hopefully will one day support dynamic program points for advanced debugging.
 * Though this may be better done in Object itself since it applies to all things.
 * Will possibly support classification of errors using a hierarchy one day.
 */

struct _KewErrorObject {
    KewObject super;
    
    KewObject *source_point;
    KewObject *message;
};




/* LISTS
 */

struct _KewListObject {
    KewObject super;
    
    GPtrArray *array;
};

struct _KewListReaderObject {
    KewObject super;
    
    KewObject *list;
    guint index;
};


/* STRINGS
 * FIXME: move over to unicode (possibly both utf-8, utf-16 encodings) once I have a clue how it works
 */

struct _KewStringObject {
    KewObject super;
    unsigned size; /* to directly address more than word-indexed string requires segmenting it */
    char *data;
};



/* STANDARD SELECTORS
 * these are all used by the library itself.
 *
 * NOTE: Please keep these in alphabetical order.
 */

KewSelector kew_sel_at;
KewSelector kew_sel_call;
KewSelector kew_sel_containsKey;
KewSelector kew_sel_dynamicVariable;
KewSelector kew_sel_raise;
KewSelector kew_sel_string;



/* STANDARD EXTENSION KEYS
 */
 
gpointer kew_top_continuation_key;


G_END_DECLS
#endif
